/*
 * Copyright 2019 xiaomaoguai.com All right reserved. This software is the
 * confidential and proprietary information of xiaomaoguai.com ("Confidential
 * Information"). You shall not disclose such Confidential Information and shall
 * use it only in accordance with the terms of the license agreement you entered
 * into with xiaomaoguai.com.
 */

package com.xiaomaoguai.core.next.hsf.http.annotation;

import app.myoss.cloud.core.spring.support.PrefixOrSuffixBeanNameGenerator;
import com.xiaomaoguai.core.next.hsf.http.ClassPathHsfInterfaceScanner;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;

/**
 * {@link HsfHttpRequestScan} 的实现类
 *
 * @author chenyao
 * @since 2016年8月30日 上午10:28:18
 */
public class HsfHttpRequestScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {
    private ResourceLoader resourceLoader;

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        AnnotationAttributes scanAtt = AnnotationAttributes
                .fromMap(importingClassMetadata.getAnnotationAttributes(HsfHttpRequestScan.class.getName()));
        if (scanAtt != null) {
            handler(registry, scanAtt);
        }
        AnnotationAttributes scansAtt = AnnotationAttributes
                .fromMap(importingClassMetadata.getAnnotationAttributes(HsfHttpRequestScans.class.getName()));
        if (scansAtt != null) {
            AnnotationAttributes[] values = scansAtt.getAnnotationArray("value");
            for (AnnotationAttributes value : values) {
                handler(registry, value);
            }
        }
    }

    private void handler(BeanDefinitionRegistry registry, AnnotationAttributes attributes) {
        ClassPathHsfInterfaceScanner scanner = new ClassPathHsfInterfaceScanner(registry);

        scanner.setResourceLoader(resourceLoader);

        Class<? extends Annotation> annotationClass = attributes.getClass("annotationClass");
        if (!Annotation.class.equals(annotationClass)) {
            scanner.setAnnotationClass(annotationClass);
        }

        Class<?> markerInterface = attributes.getClass("markerInterface");
        if (!Class.class.equals(markerInterface)) {
            scanner.setMarkerInterface(markerInterface);
        }

        Class<? extends BeanNameGenerator> generatorClass = attributes.getClass("beanNameGenerator");
        if (PrefixOrSuffixBeanNameGenerator.class.equals(generatorClass)) {
            PrefixOrSuffixBeanNameGenerator beanNameGenerator = new PrefixOrSuffixBeanNameGenerator();
            beanNameGenerator.setBeanNamePrefix(attributes.getString("beanNamePrefix"));
            beanNameGenerator.setBeanNameSuffix(attributes.getString("beanNameSuffix"));
            scanner.setBeanNameGenerator(beanNameGenerator);
        } else if (!BeanNameGenerator.class.equals(generatorClass)) {
            scanner.setBeanNameGenerator(BeanUtils.instantiateClass(generatorClass));
        }

        scanner.setHsfHttpRequestProxyBeanName(attributes.getString("hsfHttpRequestProxyBeanName"));
        scanner.setRestTemplateBeanName(attributes.getString("restTemplateBeanName"));
        scanner.setServiceVersion(attributes.getString("serviceVersion"));
        scanner.setServerUrl(attributes.getString("serverUrl"));
        scanner.setResponseBodyDeserializerBeanName(attributes.getString("responseBodyDeserializerBeanName"));

        List<String> basePackages = new ArrayList<>();
        for (String pkg : attributes.getStringArray("value")) {
            if (StringUtils.hasText(pkg)) {
                basePackages.add(pkg);
            }
        }
        for (String pkg : attributes.getStringArray("basePackages")) {
            if (StringUtils.hasText(pkg)) {
                basePackages.add(pkg);
            }
        }
        for (Class<?> clazz : attributes.getClassArray("basePackageClasses")) {
            basePackages.add(ClassUtils.getPackageName(clazz));
        }
        scanner.registerFilters();
        scanner.doScan(StringUtils.toStringArray(basePackages));
    }
}
